/* Copyright (C) 2010 Fredrique Samuels, fredriquesamuels@gmail.com */

/*
  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#ifndef TRI_TRANSPORT_H_
#define TRI_TRANSPORT_H_


#include <string>
#include <iostream>

#include "timestamp.h"

namespace tri{
namespace transport{


#define TRANSPORT_INT 700
#define TRANSPORT_FLOAT 701
#define TRANSPORT_DOUBLE 702
#define TRANSPORT_LONG 703
#define TRANSPORT_STRING 704
#define TRANSPORT_TIMESTAMP 705
#define TRANSPORT_BIN 706


void write(std::string& s ,void * c,int size);

/**
 * Type writer functions
 */
void write(std::string& s,int& t);
void write(std::string& s,float& t);
void write(std::string& s,long& t);
void write(std::string& s,double& t);
void write(std::string& s,timestamp& t);
void write(std::string& s,std::string& t);


template<class T>
void write(std::string& s,T& t){
    write(s,t);
}


/**
 * Type reading functions
 */

void read(std::string& s,int& index,int &v);
void read(std::string& s,int& index,float &v);
void read(std::string& s,int& index,long &v);
void read(std::string& s,int& index,double &v);
void read(std::string& s,int& index,timestamp &v);
void read(std::string& s,int& index,std::string& v);
void read(std::string& s,int& index,std::string& v,int size);

template<class T>
void read_as(std::string& s,T& v){
    v = *((T*)(&s.c_str()[0]));
}

template<class T>
void read_as(std::string& s,int index,T& v){
    v = *((T*)(&s.c_str()[index]));
}

template<class T>
void read(std::string& s,int& index,T& v){
    read(s,index,v);
}


void write_type(std::string& s,int& t);
void write_type(std::string& s,float& t);
void write_type(std::string& s,long& t);
void write_type(std::string& s,double& t);
void write_type(std::string& s,timestamp& t);
void write_type(std::string& s,std::string& t);


template<class T>
void write_transport_packet(std::string& s,T& value,std::string channel= "channel",timestamp t = timestamp::now()){
    std::string v;
    int size;
    
    write(v,value);
    size  = v.size();
    std::string header("TransportPacketHeader");
    write(s,header);
    write_type(s,t);
    write(s,channel);
    write(s,t);
    write(s,size);
    s+=v;
    
}

struct packet_header{
    std::string header;
    std::string channel;
    int size;
    timestamp ts;
    int packet_type;
};

template<class T>
class packet{
public:
    packet_header header;
    T value;
};

void read_transport_packet_header(std::string& s,int &index,packet_header& h);
void read_transport_packet_header(std::string& s,packet_header& h);

template<class T>
void read_transport_packet(std::string& s,packet<T>& p){
    int index= 0;
    std::string value;
    read_transport_packet_header(s,index,p.header);
    read(s,index,p.value);
}

template<class T>
inline void print_packet(tri::transport::packet<T> &h){
    std::cout<<"<TransportPacket header="<<h.header;
    std::cout<<" value="<<h.value<<">";
}

}
}

std::ostream &operator<<(std::ostream&,tri::transport::packet_header&);



#endif
